import pygame
import sys
import random
from didiball.sprites.RadarItem import RadarItem
#from didiball.Timer import *
from pygame.locals import KEYDOWN,QUIT,K_ESCAPE,KEYUP

class DiDiBallGame():

    def __init__(self, pitch,ball,viewport,radar,sounds,timer,fps,font1,font2):
        self.__pitch = pitch
        self.__ball = ball
        self.__viewport = viewport
        self.__radar = radar
        self.sounds = sounds
        self.timer = timer
        self.clock = pygame.time.Clock()
        self.fps = fps
        self.font1 = font2
        self.font2 = font2
        
        self.is_hoofing=[False,False]
        self.is_passing=[False,False]
        
        self.__pause_keys= [pygame.locals.K_RETURN, pygame.locals.K_SPACE, pygame.locals.K_p]

    def set_teams(self, teams):
        self.teams= teams

    def tick(self):
        self.clock.tick(self.fps)

    def init(self,angle=0):
        self.__pitch.set_offset((self.__pitch.get_rect().width*2/3,self.__pitch.get_rect().height*2/3))
        for team in self.teams:
            team.init()
        self.__ball.set_pos_xy((self.__pitch.get_rect().left+self.__pitch.get_rect().width/2,self.__pitch.get_rect().top+self.__pitch.get_rect().height*0.5))
        self.__ball.set_speed_angle(90+angle)
        self.__ball.set_speed_magnitude(0.5)
        if angle == 0:
            for team in self.teams:
                team.set_score(0)
            self.timer.reset()
    
    def loop(self,screen,bg,duration):
        self.__duration= duration
        self.timer.set_duration(duration)
        self.init()
        self.prime_radar(screen)
        while self.loophandler(screen,bg):
                pass

    def vleft(self):
        self.__pitch.get_rect().left+=10
         
    def vright(self):
        self.__pitch.get_rect().left-=10
 
    def get_movement(self, team, keys):
        if keys[ team.get_controls().up ]:
            y=-1.0
        elif keys[ team.get_controls().down]:
            y=1.0
        else:
            y=0.0
        if keys[ team.get_controls().left ]:
            x=-1.0
        elif keys[ team.get_controls().right ]:
            x=1.0
        else:
            x=0.0
        return x, y
    
    
    def pause(self):
        paused= True
        while paused:
            for event in pygame.event.get():
                if (event.type == KEYDOWN):
                    if event.key in self.__pause_keys:
                        return
                    
    def loophandler(self,screen,bg):
        is_choosing=[False,False]
        for event in pygame.event.get():
            if (event.type == KEYDOWN):
                if event.key in self.__pause_keys:
                    self.pause()
                i=0
                for team in self.teams:
                    if (event.key == team.get_controls().get_hoof()):
                        self.is_hoofing[i]=True
                    elif (event.key == team.get_controls().get_pass()):
                        self.is_passing[i]=True
                    i+=1
            if (event.type == KEYUP):
                i=0
                for team in self.teams:
                    if (event.key == team.get_controls().get_hoof()):
                        self.is_hoofing[i]=False
                    elif (event.key == team.get_controls().get_pass()):
                        self.is_passing[i]=False
                    i+=1
                    
            if event.type == QUIT:
                sys.exit()
                
        #press both to choose
        i=0
        for team in self.teams:
            if self.is_hoofing[i] and self.is_passing[i]:
                is_choosing[i]= True
                self.is_hoofing[i]= False
                self.is_passing[i]= False
                i+=1
                
        coords_map= self.get_coords(screen) 
        self.unblit(screen,coords_map, bg)
        tick_ms = self.clock.tick(self.fps)
        self.timer.add_millisecond(tick_ms)
            
        if self.timer.get_minutes_part() >= self.__duration and self.teams[0].get_score()<>self.teams[1].get_score():
            self.end_game(screen)
            return False


        keys = pygame.key.get_pressed()
        if keys[K_ESCAPE]: return False

        i=0
        for team in self.teams:
            if team.is_ai():
                #get action from random ...
                self.is_hoofing[i]= False
                self.is_passing[i]= random.randint(0,100) >  90
                if not self.is_passing[i]:
                    self.is_hoofing[i]= random.randint(0,100) >  90
            #now, get movement and mod active players ..
            x,y= self.get_movement(team,keys)
            team.mod_active_players(x,y,tick_ms)
            
            #if everything's still, this is also is_choosing
            if (not team.is_ai()):
             if x==0.0 and y==0.0 and (not self.is_hoofing[i]) and (not self.is_passing[i]):
                actives= team.get_active_players()
                print "inactive!", actives
                if actives is not None and len(actives)>0:
                    dist_to_ball= actives[0].calc_distance_to(self.__ball)
                    #print " this: ", dist_to_ball
                    next_player= team.find_nearest_inactive_player(self.__ball)
                    if next_player:
                        next_dist_to_ball = next_player.calc_distance_to(self.__ball)
                        #print " that: ", next_dist_to_ball
                        if next_dist_to_ball < dist_to_ball:
                            is_choosing[i]=True
            i+=1
        
        self.__ball.mod(tick_ms)
        
        for p in self.__pitch.get_posts():
            p.collision(self.__ball,tick_ms)
        i=0
        for team in self.teams:
            if(team.collision(self.__ball,tick_ms,self.is_hoofing[i],self.is_passing[i])): 
                pass
            team.move_active_player(tick_ms)
            i+=1

        result = self.__ball.move(tick_ms,self.__pitch)
        i=0
        for team in self.teams:
                if team.is_ai():
                        team.choose_players(self.__ball)
                elif is_choosing[i]:
                        team.select_next_player(self.__ball)
                team.players_do(self.__ball,tick_ms)
                i+=1

        ball_adjusted= self.__pitch.adjust_coords(self.__ball.get_rectangular_coords())
        
        #redraw?
        if(False==self.__viewport.inner_contains(ball_adjusted)):
                #print "uh-oh"
                #movement=30*self.__ball.get_speed_magnitude()
                mag=3
                self.__pitch.undraw_lines(screen)
                #left
                if self.__viewport.get_inner().left > ball_adjusted[0]:
                        if self.__pitch.get_offset()[0] < +20:
                                self.__pitch.shiftx((self.__viewport.get_inner().left-ball_adjusted[0])/mag)
                #right
                elif self.__viewport.get_inner().left + self.__viewport.get_inner().width < ball_adjusted[0]:
                        if self.__pitch.get_offset()[0] > -self.__pitch.get_rect().width+100:
                                self.__pitch.shiftx((self.__viewport.get_inner().left + self.__viewport.get_inner().width - ball_adjusted[0])/mag)
                #top
                if self.__viewport.get_inner().top > ball_adjusted[1]:
                        if self.__pitch.get_offset()[1] < -10:
                                self.__pitch.shifty((self.__viewport.get_inner().top - ball_adjusted[1])/mag)
                #bottom 
                elif self.__viewport.get_inner().top + self.__viewport.get_inner().height < ball_adjusted[1]:
                        if self.__pitch.get_offset()[1] > -self.__pitch.get_rect().height+100:
                                self.__pitch.shifty((self.__viewport.get_inner().top + self.__viewport.get_inner().height - ball_adjusted[1])/mag)
                self.__pitch.redraw_lines(screen)

        self.timer.blit_to(screen,self.font1)

        self.__ball.blit_to_shifting_plane(screen,self.__pitch)

        for team in self.teams:
            team.refresh_players(tick_ms,self.__ball)
            team.blit_to(screen,self.font1,self.font2)

        self.update_radar(screen)
        pygame.display.update()
        if result <> 0:
            self.goal(screen,self.teams[result-1],bg)
        return True        


    def prime_radar(self,screen):
        items= {}
        for team in self.teams:
                for p in team.players:
                        k= "{0}:{1}".format(team.is_r2l(),p.get_caption())
                        pos= p.get_pos_xy()
                        items[k]= RadarItem(pos,team.get_colour())
        #items['ball'] = RadarItem(self.__ball.get_pos_xy(),(255,255,0))
        items['ball'] = RadarItem((-1,-1),(255,255,0))
        self.__radar.set_radar_items(items)     
        #self.__radar.blit_to(screen)


    def get_coords(self,screen):
        coords_map={}
        for team in self.teams:
            coords_map= team.calc_adjusted_coords(screen,coords_map)
        #self.__ball.unblit_to_shifting_plane(screen, self.__pitch, bg)
        coords_map['ball']=self.__ball.calc_adjusted_coords(screen, self.__pitch)
        return coords_map


    def update_radar(self,screen):
        self.__radar.blit_to(screen)
        positions= {}
        for team in self.teams:
                for p in team.players:
                        k= "{0}:{1}".format(team.is_r2l(),p.get_caption())
                        v= p.get_pos_xy()
                        positions[k]=v
        positions['ball'] = self.__ball.get_pos_xy()
        #print "positions: {0}".format(positions)
        self.__radar.update_positions(positions,screen)

    def goal(self,screen,team,bg):
        #self.sounds['goal'].play()
        
        team.inc_score()
        goal_message = "GOAL for {0}!!!".format(team.get_name())
        goal_label = self.font2.render(goal_message, 1, (255,255,0))
       
        screen.blit(goal_label,(screen.get_width()*0.5-goal_label.get_width()*0.5,screen.get_height()*0.5))
        pygame.display.update()
        pygame.time.wait(4000)
        if team.is_r2l()==False:
            self.init(-25)
        else:
            self.init(25)
 
        screen.blit(bg,(screen.get_width()*0.5-goal_label.get_width()*0.5,screen.get_height()*0.5),goal_label.get_rect())
        screen.blit(bg,(0,0)) #screen.get_width()*0.5-goal_label.get_width()*0.5,screen.get_height()*0.5),goal_label.get_rect())
        pygame.display.update()
        self.clock.tick(self.fps)

    def get_winner(self):
        if self.teams[0].get_score()>self.teams[1].get_score():
                return 0
        else:
                return 1
    def get_loser(self):
        return 1-self.get_winner()

    def end_game(self,screen):
        #self.sounds['end'].play()
        
        end = "'{0}' Won!".format(self.teams[self.get_winner()].get_name())
        end_label = self.font2.render(end, 1, (255,255,0))
        screen.blit(end_label,(screen.get_width()*0.5-end_label.get_width()*0.5,screen.get_height()*0.5))
        
        end = "Score {0}-{1} after {2}".format(self.teams[self.get_winner()].get_score(),self.teams[self.get_loser()].get_score(),str(self.timer))
        end_label = self.font2.render(end, 1, (255,255,0))
        screen.blit(end_label,(screen.get_width()*0.5-end_label.get_width()*0.5,screen.get_height()*0.6))
        pygame.display.update()
        pygame.time.wait(5000)     
        self.clock.tick(self.fps)    


    def unblit(self,screen,coords_map,bg):
        for coordskey in coords_map:
                screen.blit(bg,coords_map[coordskey],coords_map[coordskey])
